
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */

// 头文件包含保护
#ifndef _NGX_CONFIG_H_INCLUDED_
#define _NGX_CONFIG_H_INCLUDED_

// 包含一个自动生成的头文件
// ngx_auto_headers.h 通常是由 Nginx 的 configure 脚本自动生成的。
// 它用于检测并定义特定操作系统或编译器特有的头文件是否存在，以及一些平台相关的特性宏。
// 这为后续代码提供了可移植的基础。
// 位置在 objs/ngx_auto_config.h
#include <ngx_auto_headers.h>


// 处理 DragonFly BSD 系统的兼容性
// DragonFly BSD 是从 FreeBSD 4.x 分支出来的
#if defined __DragonFly__ && !defined __FreeBSD__
#define __FreeBSD__        4
#define __FreeBSD_version  480101
#endif

// 这些头文件在 src/os/ 下面
#if (NGX_FREEBSD)
#include <ngx_freebsd_config.h>


#elif (NGX_LINUX)
#include <ngx_linux_config.h>


#elif (NGX_SOLARIS)
#include <ngx_solaris_config.h>


#elif (NGX_DARWIN)
#include <ngx_darwin_config.h>


#elif (NGX_WIN32)
#include <ngx_win32_config.h>

// 如果以上所有特定平台的条件都不满足，则默认包含一个符合 POSIX 标准的通用配置文件
// 为了保证最大程度的可移植性，为那些不完全属于上述类别但大体遵循 POSIX 标准的系统提供一个基准配置
#else /* POSIX */
#include <ngx_posix_config.h>

#endif

// 设置一个默认值，定义 Nginx 拥有 SO_SNDLOWAT 套接字选项
// SO_SNDLOWAT 是套接字发送缓冲区的低水位标记。
// 某些系统可能不支持此选项。
// 如果之前的平台配置（如 ngx_linux_config.h）没有定义 NGX_HAVE_SO_SNDLOWAT（通常是因为检测到系统不支持），
// 这里就提供一个默认支持的定义。这是一种安全后备（Fallback）
#ifndef NGX_HAVE_SO_SNDLOWAT
#define NGX_HAVE_SO_SNDLOWAT     1
#endif

// 非win32，即unix
#if !(NGX_WIN32)

// 宏函数，用于构造信号名
// ngx_signal_value(QUIT) 会被展开为 SIGQUIT
// 使用辅助宏 ngx_signal_helper 是为了确保正确的宏拼接(##)发生
#define ngx_signal_helper(n)     SIG##n
#define ngx_signal_value(n)      ngx_signal_helper(n)

// 产生随机数
// 种子在ngx_worker_process_init里初始化
// srandom(((unsigned) ngx_pid << 16) ^ tp->sec ^ tp->msec);
#define ngx_random               random

// 重定义 unix 信号：集中管理信号定义，提高代码可读性和可维护性
// NGX_SHUTDOWN_SIGNAL: 优雅关闭（平滑重启）信号
// NGX_TERMINATE_SIGNAL: 立即终止信号
// NGX_NOACCEPT_SIGNAL: 停止接收新连接信号
// NGX_RECONFIGURE_SIGNAL: 重新加载配置文件信号
/* TODO: #ifndef */
#define NGX_SHUTDOWN_SIGNAL      QUIT
#define NGX_TERMINATE_SIGNAL     TERM
#define NGX_NOACCEPT_SIGNAL      WINCH
#define NGX_RECONFIGURE_SIGNAL   HUP

// 根据是否使用 LinuxThreads（一个旧的 Linux 线程实现）来定义另外两个信号。
// NGX_REOPEN_SIGNAL: 重新打开日志文件信号
// NGX_CHANGEBIN_SIGNAL: 升级二进制文件（热部署）信号
// LinuxThreads 的实现与信号交互时有特殊问题，可能占用了 USR1 和 USR2 信号。
// 因此，如果使用 LinuxThreads，就需要选择两个不冲突的其他信号（INFO 和 XCPU）
#if (NGX_LINUXTHREADS)
#define NGX_REOPEN_SIGNAL        INFO
#define NGX_CHANGEBIN_SIGNAL     XCPU
#else
#define NGX_REOPEN_SIGNAL        USR1
#define NGX_CHANGEBIN_SIGNAL     USR2
#endif

// 定义函数调用约定为空
// 在类 Unix 系统上，通常使用默认的 C 调用约定（cdecl），但不需要显式声明。
// 这些宏在 Windows 上会有不同的定义（例如 __cdecl），这里为非 Windows 平台提供空定义，保持代码跨平台一致性
#define ngx_cdecl
#define ngx_libc_cdecl

#endif /* !(NGX_WIN32) */

// nginx内部标准整数定义
// ngx_rbtree_key_t = ngx_uint_t (ngx_rbtree.h)
// ngx_rbtree_key_int_t = ngx_int_t(ngx_rbtree.h)
// ngx_msec_t = ngx_rbtree_key_t = ngx_uint_t (ngx_time.h)
// ngx_msec_int_t = ngx_rbtree_key_int_t ngx_int_t(ngx_time.h)

// ngx_int_t 和 ngx_uint_t: 
// 使用 intptr_t 和 uintptr_t 能保证这些类型的长度足以存放指针值。
// 这意味着在 32 位系统上它们是 32 位，在 64 位系统上是 64 位，
// 确保了在不同平台间移植时，整型的大小与指针大小相匹配，避免溢出和精度问题
typedef intptr_t        ngx_int_t;
typedef uintptr_t       ngx_uint_t;
typedef intptr_t        ngx_flag_t; //相当于bool，标志量用

// 定义 32 位和 64 位有符号整数转换为字符串后的最大可能长度（包括负号）
// sizeof 计算字符串字面量包含终止符 \0，所以减 1 得到纯数字字符串的长度
#define NGX_INT32_LEN   (sizeof("-2147483648") - 1) // 11
#define NGX_INT64_LEN   (sizeof("-9223372036854775808") - 1)    // 20

// 根据指针大小（NGX_PTR_SIZE，由 configure 检测）定义 ngx_int_t 类型的字符串长度和最大值
// ngx_int_t 是基于 intptr_t 的，它的长度取决于平台是 32 位还是 64 位
// 指针长度是 4 字节，32 位 CPU
#if (NGX_PTR_SIZE == 4)
#define NGX_INT_T_LEN   NGX_INT32_LEN
#define NGX_MAX_INT_T_VALUE  2147483647

#else
// 指针长度是 8 字节，64 位 CPU
#define NGX_INT_T_LEN   NGX_INT64_LEN
#define NGX_MAX_INT_T_VALUE  9223372036854775807
#endif

// 分配内存时的字节对齐的基准单位。内存对齐能显著提高 CPU 访问内存的效率
// 如果没有在其他地方定义，则默认使用 unsigned long 的长度作为对齐字节数
// 64 位上是 8 字节
#ifndef NGX_ALIGNMENT
#define NGX_ALIGNMENT   sizeof(unsigned long)    /* platform word */
#endif

// 内存对齐宏
// 将整数 d 向上对齐到 a 的倍数，a 是2的幂
// (((d) + (a - 1)) & ~(a - 1)) = a * ceil(d / a)
#define ngx_align(d, a)     (((d) + (a - 1)) & ~(a - 1))
// 将指针 p 向上对齐到 a 的倍数
#define ngx_align_ptr(p, a)                                                   \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
// 高效的内存分配器（如 Nginx 的池、 slab 等）需要保证分配的内存地址是对齐的。
// 这两个宏是实现这一目标的核心工具。
// 算法原理是：加上（对齐值减一），然后掩去低位
/*
a = 16 = 00010000
a - 1 = 15 = 00001111
d = 13 = 00001101
d + (a - 1) = 13 + 15 = 28 
d + (a - 1) = 00001101 + 00001111 = 00011100
~(a - 1) = 11110000
(d + (a - 1)) & ~(a - 1) = 00011100 & 11110000 = 00010000 (16)

a = 16 时
数值范围:  0-15 → 对齐到 0
         16-31 → 对齐到 16
         32-47 → 对齐到 32
         48-63 → 对齐到 48
         ...
*/

// 将 ngx_abort 映射到标准 C 库的 abort() 函数
#define ngx_abort       abort

/* TODO: platform specific: array[NGX_INVALID_ARRAY_INDEX] must cause SIGSEGV */
// 定义一个无效的数组索引值
// 用作特殊标记或错误返回值，指示索引越界或无效。
// 选择这个值（负数的二进制补码表示）是希望在某些平台上访问这个索引时能直接导致段错误（SIGSEGV），从而快速暴露 bug
#define NGX_INVALID_ARRAY_INDEX 0x80000000

/* TODO: auto_conf: ngx_inline   inline __inline __inline__ */
// 定义内联函数关键字
// 不同的编译器对 inline 关键字的支持可能不同（如 __inline__, __inline）。
// 这个宏提供了一个统一的方式。
// 如果其他地方（可能是编译器特定的配置）没有定义 ngx_inline，则默认使用 C99 标准的 inline
// ngx_inline通常需要配合static使用
// 在nginx unit里的定义是：
// static inline __attribute__((always_inline))
#ifndef ngx_inline
#define ngx_inline      inline
#endif

// 定义 INADDR_NONE 常量（表示无效的 IP 地址）
// 大多数系统在 <netinet/in.h> 中定义了这个常量，但某些系统（如注释中指出的 Solaris）可能没有。
// 这里提供一个后备定义，确保代码的可移植性
#ifndef INADDR_NONE  /* Solaris */
#define INADDR_NONE  ((unsigned int) -1)
#endif

// 定义主机名的最大长度
// 如果系统头文件（如 <sys/param.h>）定义了 MAXHOSTNAMELEN，就使用系统的定义。
// 否则，提供一个合理的默认值（256）。这避免了硬编码可能存在的平台差异。
#ifdef MAXHOSTNAMELEN
#define NGX_MAXHOSTNAMELEN  MAXHOSTNAMELEN
#else
#define NGX_MAXHOSTNAMELEN  256
#endif

// 定义 32 位无符号整数和有符号整数的最大值。
// 提供清晰、明确的极值常量，增强代码可读性并避免魔术数字（Magic Number）。
#define NGX_MAX_UINT32_VALUE  (uint32_t) 0xffffffff
#define NGX_MAX_INT32_VALUE   (uint32_t) 0x7fffffff

// 兼容性占位符
#if (NGX_COMPAT)

#define NGX_COMPAT_BEGIN(slots)  uint64_t spare[slots];
#define NGX_COMPAT_END

#else

#define NGX_COMPAT_BEGIN(slots)
#define NGX_COMPAT_END

#endif


#endif /* _NGX_CONFIG_H_INCLUDED_ */
